package com.jade.bss.base.account.impl;

import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.bss.base.BssException;
import com.jade.bss.base.account.Account;
import com.jade.bss.base.account.AccountDao;
import com.jade.bss.base.account.AccountRecord;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.sql.SqlUtils;
import com.jade.framework.base.util.PagingList;


/**
 * 采用JPA方式实现的数据访问接口。
 *
 * @author dwzhang
 * @version 1.0 12-04-22 下午10:05
 */
@Named ("bss_accountDao")
public class JpaAccountDao
        implements AccountDao
{
    @PersistenceContext (unitName = "default")
    protected EntityManager em;

    public void setEntityManager(EntityManager em)
    {
        this.em = em;
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", key = "$1.id"),
//                   @CacheEvict (group = "bss.acc.gt", sub_group = "$1.enterpriseId", key = "$1.type"),
//                   @CacheEvict (group = "bss.acc.l", sub_group = "$1.enterpriseId", allEntries = true)})
    public void addAccount(Account account)
            throws BssException
    {
        em.persist(account);
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", key = "$1.id"),
//                   @CacheEvict (group = "bss.acc.gt", sub_group = "$1.enterpriseId", key = "$1.type"),
//                   @CacheEvict (group = "bss.acc.l", sub_group = "$1.enterpriseId", allEntries = true)})
    public void updateAccount(Account account)
            throws BssException
    {
        em.merge(account);
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", key = "$1.id"),
//                   @CacheEvict (group = "bss.acc.gt", sub_group = "$1.enterpriseId", key = "$1.type"),
//                   @CacheEvict (group = "bss.acc.l", sub_group = "$1.enterpriseId", allEntries = true)})
    public void updateAccount(Account account, long remnant, long prepay, long freeze)
            throws BssException
    {
        String sql = "UPDATE Account SET remnant = remnant + :remnant, prepay = prepay + :prepay, " +
                "freeze = freeze + :freeze WHERE id=:id";
        Query query = em.createQuery(sql);
        query.setParameter("remnant", remnant);
        query.setParameter("prepay", prepay);
        query.setParameter("freeze", freeze);
        query.setParameter("id", account.getId());
        query.executeUpdate();
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", allEntries = true),
//                   @CacheEvict (group = "bss.acc.gt", sub_group = "$1", key = "$2"),
//                   @CacheEvict (group = "bss.acc.l", sub_group = "$1", allEntries = true)})
    public void removeAccount(String ownerType, String ownerId, String type)
            throws BssException
    {
        String sql = "DELETE FROM Account WHERE ownerType=:ownerType and ownerId=:ownerId and type=:type";
        Query query = em.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        query.setParameter("type", type);
        query.executeUpdate();
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", key = "$1"), @CacheEvict (group = "bss.acc.gt", allEntries = true),
//                   @CacheEvict (group = "bss.acc.l", allEntries = true)})
    public void removeAccount(long id)
            throws BssException
    {
        String sql = "DELETE FROM Account WHERE id=:id";
        Query query = em.createQuery(sql);
        query.setParameter("id", id);
        query.executeUpdate();
    }

    //    @CacheEvicts ({@CacheEvict (group = "bss.acc.g", allEntries = true),
//                   @CacheEvict (group = "bss.acc.gt", sub_group = "$1", allEntries = true),
//                   @CacheEvict (group = "bss.acc.l", sub_group = "$1", allEntries = true)})
    public void removeAllAccount(String ownerType, String ownerId)
            throws BssException
    {
        String sql = "DELETE FROM Account WHERE ownerType=:ownerType and ownerId=:ownerId";
        Query query = em.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        query.executeUpdate();
    }

    //    @SuppressWarnings (value = "unchecked")
//    @Cacheable (group = "bss.acc.gt", sub_group = "$1", key = "$2")
    public Account getAccount(String ownerType, String ownerId, String type)
    {
        String sql = "SELECT account FROM Account account WHERE ownerType=:ownerType and ownerId=:ownerId AND type=:type";
        Query query = em.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        query.setParameter("type", type);
        List<Account> result = query.getResultList();
        if (result.isEmpty()) {
            return null;
        }
        else {
            return result.get(0);
        }
    }

    //    @Cacheable (group = "bss.acc.g", key = "$1")
    public Account getAccount(long id)
    {
        return em.find(Account.class, id);
    }

    //    @SuppressWarnings (value = "unchecked")
//    @Cacheable (group = "bss.acc.l", sub_group = "$1", key = "all")
    public List<Account> listAccount(String ownerType, String ownerId)
    {
        String sql = "SELECT account FROM Account account WHERE ownerType=:ownerType and ownerId=:ownerId";
        Query query = em.createQuery(sql);
        query.setParameter("ownerType", ownerType);
        query.setParameter("ownerId", ownerId);
        return query.getResultList();
    }

    public void addAccountRecord(AccountRecord accountRecord)
            throws BssException
    {
        em.persist(accountRecord);
    }

    public void updateAccountRecord(AccountRecord accountRecord)
            throws BssException
    {
        em.merge(accountRecord);
    }

    public AccountRecord getAccountRecord(long recordId)
    {
        return em.find(AccountRecord.class, recordId);
    }

    public PagingList<Account> queryAccount(Criteria criteria)
    {
        String sql = "SELECT account From Account account";
        return SqlUtils.sqlQuery(sql,em,criteria);
    }

    public PagingList<AccountRecord> queryAccountRecord(Criteria criteria)
    {
        String sql = "SELECT accountRecord FROM AccountRecord accountRecord";
        return SqlUtils.sqlQuery(sql, em, criteria);
    }
}
